﻿using DevExpress.Utils.MVVM;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DevUIUtils
{
    public class LabelEx : Label, ISupportCommandBinding
    {
        public LabelEx()
        {
            this.BackColor = Color.Transparent;
            this.MouseEnter += (sender, e) =>
            {
                if (this.BackColorHover != null)
                {
                    base.BackColor = this.BackColorHover.Value;
                }
            };
            this.MouseLeave += (sender, e) =>
            {
                if (this.SaveBackColor != null)
                {
                    base.BackColor = this.SaveBackColor.Value;
                }
            };
        }

        [Browsable(true)]
        public override Color BackColor
        {
            get => base.BackColor;
            set
            {
                base.BackColor = value;
                this.SaveBackColor = value;
            }
        }

        [Browsable(true)]
        public virtual Color? BackColorHover { get; set; } = null;

        [Browsable(true)]
        public virtual Color? SaveBackColor { get; set; } = null;

        // 摘要:
        //     Binds the specific parameterized command to this DevExpress.XtraEditors.BaseButton
        //     .
        //
        // 参数:
        //   command:
        //     An Object that is the command to be bound to this DevExpress.XtraEditors.BaseButton.
        //
        //   queryCommandParameter:
        //     A Func delegate that passes the specific Object to the command as a parameter.
        //
        //   updateState:
        //     An Action that uses the boolean function to specify whether or not this DevExpress.XtraEditors.BaseButton
        //     is currently enabled.
        //
        // 返回结果:
        //     An IDisposable object. Disposing of this object unbinds the command from this
        //     DevExpress.XtraEditors.BaseButton.
        public virtual IDisposable BindCommand(object command, Func<object> queryCommandParameter = null, Action<Control, Func<bool>> updateState = null)
        {
            if (updateState == null)
            {
                updateState = delegate (Control button, Func<bool> canExecute)
                {
                    button.Enabled = canExecute();
                };
            }

            return CommandHelper.Bind(this, delegate (Control button, Action execute)
            {
                button.Click += delegate
                {
                    execute();
                };
            }, updateState, command, queryCommandParameter);
        }

        // 摘要:
        //     Uses the command selector to find an appropriate parameterized command in the
        //     source and bind it to this DevExpress.XtraEditors.BaseButton.
        //
        // 参数:
        //   commandSelector:
        //     An Expression that selects the appropriate command from the source object.
        //
        //   source:
        //     An Object (typically, a ViewModel) where the commandSelector looks for the required
        //     command.
        //
        //   queryCommandParameter:
        //     A Func delegate that passes the specific Object to the command as a parameter.
        //
        //   updateState:
        //     An Action that specifies whether this DevExpress.XtraEditors.BaseButton is currently
        //     enabled.
        //
        // 返回结果:
        //     An IDisposable object. Disposing of this object unbinds the command from this
        //     DevExpress.XtraEditors.BaseButton.
        public virtual IDisposable BindCommand(Expression<Action> commandSelector, object source, Func<object> queryCommandParameter = null, Action<Control, Func<bool>> updateState = null)
        {
            if (updateState == null)
            {
                updateState = delegate (Control button, Func<bool> canExecute)
                {
                    button.Enabled = canExecute();
                };
            }

            return CommandHelper.Bind(this, delegate (Control button, Action execute)
            {
                button.Click += delegate
                {
                    execute();
                };
            }, updateState, commandSelector, source, queryCommandParameter);
        }

        //
        // 摘要:
        //     Uses the command selector to find an appropriate parameterized command of the
        //     target type in the source and bind it to this DevExpress.XtraEditors.BaseButton.
        //
        // 参数:
        //   commandSelector:
        //     An Expression that selects the appropriate command from the source object.
        //
        //   source:
        //     An Object (typically, a ViewModel) where the commandSelector looks for the required
        //     command.
        //
        //   queryCommandParameter:
        //     A Func delegate that passes the specific Object to the command as a parameter.
        //
        //   updateState:
        //     An Action that specifies whether this DevExpress.XtraEditors.BaseButton is currently
        //     enabled.
        //
        // 类型参数:
        //   T:
        //     The type of a ViewModel that stores a bindable command.
        //
        // 返回结果:
        //     An IDisposable object. Disposing of this object unbinds the command from this
        //     DevExpress.XtraEditors.BaseButton.
        public virtual IDisposable BindCommand<T>(Expression<Action<T>> commandSelector, object source, Func<T> queryCommandParameter = null, Action<Control, Func<bool>> updateState = null)
        {
            if (updateState == null)
            {
                updateState = delegate (Control button, Func<bool> canExecute)
                {
                    button.Enabled = canExecute();
                };
            }

            return CommandHelper.Bind(this, delegate (Control button, Action execute)
            {
                button.Click += delegate
                {
                    execute();
                };
            }, updateState, commandSelector, source, () => (queryCommandParameter != null) ? queryCommandParameter() : default);
        }

        IDisposable ISupportCommandBinding.BindCommand(object command, Func<object> queryCommandParameter)
        {
            return BindCommand(command, queryCommandParameter);
        }

        IDisposable ISupportCommandBinding.BindCommand(Expression<Action> commandSelector, object source, Func<object> queryCommandParameter)
        {
            return BindCommand(commandSelector, source, queryCommandParameter);
        }

        IDisposable ISupportCommandBinding.BindCommand<T>(Expression<Action<T>> commandSelector, object source, Func<T> queryCommandParameter)
        {
            return BindCommand(commandSelector, source, queryCommandParameter);
        }
    }
}
